/*

This program file is part of luacalc
(C) 2006 Richard Simes
You may distribute it under the terms of the GNU General Public License

*/
#include "luacalcgrid.h"
#include "luacalcconfig.h"
#include <iostream>

using namespace std;


/**
 *  Set up the grid.
 */
LuaCalcGrid::LuaCalcGrid(wxGrid* g)
{
	this->grid = g;
	int err = 0;
	/* open the lua state */
	L = lua_open();
	//graphical input/show
	lua_pushcfunction(L, l_showMessage);
	lua_setglobal(L, "show");
	lua_pushcfunction(L, l_input);
	lua_setglobal(L, "input");

	luaL_openlibs(L);  /* open libraries */

	char fname[strlen(INSTALL_PREFIX)+strlen("luacalc.lua")+2];
	sprintf(fname, "%s%s", INSTALL_PREFIX, "/luacalc.lua");

	// equivalent to package.path="./?.lua;./?.lc;"..INSTALL_PREFIX.."/?.lua"
	char path[strlen("./?.lua;./?.lc;")+strlen(INSTALL_PREFIX)+strlen("/?.lua")+1];
	sprintf(path, "./?.lua;./?.lc;%s/?.lua", INSTALL_PREFIX);
	lua_getfield(L, LUA_GLOBALSINDEX, "package");
	lua_pushstring(L, path);
	lua_setfield(L, -2, "path");
	lua_pop(L, 1);


	/* load the file. */
	if ((err=luaL_loadfile(L, fname))==0){
		// Push the function name onto the stack
		if ((err = lua_pcall (L, 0, LUA_MULTRET, 0)) == 0){
			lua_pushstring (L, "hello");
			// Function is located in the Global Table
			lua_gettable (L, LUA_GLOBALSINDEX);
			lua_pcall (L, 0, 0, 0);
		}else{
			cerr << "couldn't load main" << endl;
			exit(1);
		}
	}else{
		std::cerr << "couldn't load file" << fname << std::endl;
		exit(2);
	}

}

/**
*  Returns the number of rows to display
*/
int LuaCalcGrid::GetNumberRows(){
	return MAX_ROWS;
}

/**
*	Returns the number of columns to display.
*/
int LuaCalcGrid::GetNumberCols(){
	return MAX_COLS;

}

/**
* Always returns false - querying Lua to ask if the value is empty takes
* time that doesn't need to be taken.
*/
bool LuaCalcGrid::IsEmptyCell(int row, int col){ return false;}

/**
* Get the value/result for the specified cell.
* The UI calls this method to display each cell, so all functions are evaluated
* and the result is returned.
*/
wxString LuaCalcGrid::GetValue(int row, int col){
    //increment vals - Lua indexes start at 1.
    col++;
    row++;
    //put the get method on the lua stack
    lua_getfield(L, LUA_GLOBALSINDEX, "get");
    // push the paramaters.
    lua_pushinteger(L, col);
    lua_pushinteger(L, row);

    // call the method with 2 input paramaters and 1 returned result.
    lua_call(L, 2, 1);

    size_t* len= new size_t;
    /* return value is at the top of the stack. */
    const char* str = lua_tolstring(L, lua_gettop(L), len);
    lua_pop(L, 1);
    if (*len > 0 /*and *len < 50*/){
        wxString st(str, wxConvUTF8);
        return st;
    } else {
        return wxString(_(""));
    }
}

/**
* Method called when a user inputs a value to the spreadsheet.
*/
void LuaCalcGrid::SetValue(int row, int col, const wxString& value){
    // convert to 1-based indices
    col++;
    row++;
    // call the set method
    lua_getfield(L, LUA_GLOBALSINDEX, "set");
    lua_pushinteger(L, row);
    lua_pushinteger(L, col);
    lua_pushstring(L, value.mb_str(wxConvUTF8));
    lua_call(L, 3, 0);
    // need to tell the UI to recalculate all cells.
    // theoretically could optimise this to only recalculating effected cells.
   // grid->ForceRefresh();

}
/**
* all values are of type 'wxString'
*/
wxString LuaCalcGrid::GetTypeName(int row, int col) { return _("wxString");}

//Data type determination and value access.
bool LuaCalcGrid::CanGetValueAs(int row, int col, const wxString& typeName){ return true;}
bool LuaCalcGrid::CanSetValueAs(int row, int col, const wxString& typeName){ return true;}
long LuaCalcGrid::GetValueAsLong(int row, int col){
 // std::cout << "getting long" << std::endl;
  return 0;}
double LuaCalcGrid::GetValueAsDouble(int row, int col){return 0;}
bool LuaCalcGrid::GetValueAsBool(int row, int col){return true;}
void LuaCalcGrid::SetValueAsLong(int row, int col, long value){}
void LuaCalcGrid::SetValueAsDouble(int row, int col, double value){}
void LuaCalcGrid::SetValueAsBool(int row, int col, bool value){}
/**
* should never get called - we have no custom types.
*/
void* LuaCalcGrid::GetValueAsCustom(int row, int col, const wxString& typeName){
 // cout << "getting custom" << endl;
  return NULL;
}
void LuaCalcGrid::SetValueAsCustom(int row, int col, const wxString& typeName, void* value){}


 static int l_showMessage (lua_State *L) {
	const char* str = lua_tolstring(L, 1, NULL);  /* get argument */
	wxString st(str, wxConvUTF8);
	wxMessageBox(st);
	return 0;  /* no results returned */
}


static int l_input(lua_State *L) {
	const char* str = lua_tolstring(L, 1, NULL);  /* get argument */
	wxString st(str, wxConvUTF8);
	st = wxGetTextFromUser(st);
	lua_pushstring(L, st.mb_str(wxConvUTF8));
	return 1;  /* no results returned */
}
